Remediation scripts/Customize Endpoint Protection Recommendation/Modules/EndPointProtectionDSC/AzureGuestConfigurationPolicy/AzureGuestPolicyHelper.psm1 (237 lines of code) (raw):
function New-EPDSCAzureGuestConfigurationPolicyPackage {
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
HelpMessage = '[string] Resource Group Name')]
[ValidateNotNullOrEmpty()]
[string]$ResourceGroupName,
[Parameter(Mandatory = $false,
HelpMessage = '[string] Location')]
[string]$ResourceGroupLocation = 'eastus',
[Parameter(Mandatory = $true,
HelpMessage = '[string] Storage Account Name')]
[ValidateNotNullOrEmpty()]
[string]$storageAccountName,
[Parameter(Mandatory = $false,
HelpMessage = '[string] Storage SKU Name')]
[string]$storageSKUName = 'Standard_LRS',
[Parameter(Mandatory = $false,
HelpMessage = '[string] Provide policy scope, default to same subscription of target Resource Group, can also choose Management Group')]
[ValidateSet('subscription', 'managementGroup')]
[string]$policyScope = 'subscription'
)
Write-Host "Connecting to Azure..." -NoNewLine
Connect-AzAccount | Out-Null
# Select Management Group for policy scope
$managementGroupId = $null
if ($policyScope -eq 'managementGroup') {
$managementGroupId = Select-ManagementGroup
}
# Select a subscription to create Resource Group and Storage Account
Select-Subscription
Write-Host "Done" -ForegroundColor Green
Write-Host "Checking if policy already published, if so incrementing version..."
$PublishedPolicy = $null
$PublishedPolicy = Get-AzPolicyDefinition | Where-Object {$_.Properties.DisplayName -eq 'Monitor Antivirus'}
if ($PublishedPolicy) {
$PreviousVersion = $null
[version]$PreviousVersion = $PublishedPolicy.Properties.Metadata.guestConfiguration.version
[version]$NewVersion = [version]::new($PreviousVersion.Major,$PreviousVersion.Minor,$PreviousVersion.Build+1)
} else {
[version]$NewVersion = [version]::new(1,0,0)
}
[string]$Version = $NewVersion.ToString()
$PackageName = "MonitorAntivirus_$Version"
Write-Host "Compiling Configuration into a MOF file..." -NoNewLine
if (Test-Path 'MonitorAntivirus') {
Remove-Item "MonitorAntivirus" -Recurse -Force -Confirm:$false
}
& "$PSScriptRoot/Configurations/MonitorAntivirus.ps1" | Out-Null
Write-Host "Done" -ForegroundColor Green
Write-Host "Generating Guest Configuration Package..." -NoNewLine
New-GuestConfigurationPackage -Name $PackageName `
-Configuration "$env:Temp/MonitorAntivirus/MonitorAntivirus.mof" -Force | Out-Null
Write-Host "Done" -ForegroundColor Green
Write-Host "Publishing Package to Azure Storage..." -NoNewLine
$Url = Publish-EPDSCPackage -ResourceGroupName $ResourceGroupName `
-StorageAccountName $StorageAccountName.ToLower() `
-StorageSKUName $StorageSKUName `
-ResourceGroupLocation $ResourceGroupLocation `
-Version $Version
Write-Host "Done" -ForegroundColor Green
Write-Host "Generating Guest Configuration Policy..." -NoNewLine
if (Test-Path 'policies') {
Remove-Item "policies" -Recurse -Force -Confirm:$false
}
Import-LocalizedData -BaseDirectory "$PSScriptRoot/ParameterFiles/" `
-FileName "EPAntivirusStatus.Params.psd1" `
-BindingVariable ParameterValues | Out-Null
New-GuestConfigurationPolicy `
-ContentUri $Url `
-DisplayName 'Monitor Antivirus' `
-Description 'Audit if a given Antivirus Software is not enabled on Windows machine.' `
-Path './policies' `
-Platform 'Windows' `
-Version $Version `
-Parameter $ParameterValues -Verbose | Out-Null
Write-Host "Done" -ForegroundColor Green
Write-Host "Publishing Guest Configuration Policy..." -NoNewLine
switch ($policyScope) {
subscription { Publish-GuestConfigurationPolicy -Path ".\policies" -Verbose | Out-Null }
managementGroup { Publish-GuestConfigurationPolicy -Path ".\policies" -ManagementGroupName $managementGroupId -Verbose | Out-Null }
}
Write-Host "Done" -ForegroundColor Green
}
function Publish-EPDSCPackage {
[CmdletBinding()]
[OutputType([System.String])]
param(
[Parameter(Mandatory = $true)]
[System.String]
$ResourceGroupName,
[Parameter(Mandatory = $true)]
[System.String]
$StorageAccountName,
[Parameter(Mandatory = $true)]
[System.String]
$StorageSKUName,
[Parameter(Mandatory = $true)]
[System.String]
$ResourceGroupLocation,
[Parameter(Mandatory = $true)]
[System.String]
$Version
)
$resourceGroup = Get-AzResourceGroup $ResourceGroupName -ErrorAction "SilentlyContinue"
if ($null -eq $resourceGroup) {
$resourceGroup = New-AzResourceGroup -Name $ResourceGroupName `
-Location $ResourceGroupLocation
}
$storageAccount = Get-AzStorageAccount -Name $StorageAccountName `
-ResourceGroupName $ResourceGroupName -ErrorAction "SilentlyContinue"
if ($null -eq $storageAccount) {
$storageAccount = New-AzStorageAccount -Name $StorageAccountName `
-ResourceGroupName $ResourceGroupName `
-SkuName $StorageSKUName `
-Location $ResourceGroupLocation
}
# Wait until storage account is successfully created
do {
Start-Sleep -Seconds 3
} until (Get-AzStorageAccount -Name $StorageAccountName `
-ResourceGroupName $ResourceGroupName -ErrorAction "SilentlyContinue")
# Get Storage Context
$storageContext = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName `
-Name $StorageAccountName | `
ForEach-Object { $_.Context }
# Enable Static Web
Enable-AzStorageStaticWebsite -Context $storageContext
# Upload to static web
$blobName = "MonitorAntivirus_$Version.zip"
Set-AzStorageblobcontent -File $($env:Temp + "/MonitorAntivirus_$Version/MonitorAntivirus_$Version.zip") `
-Container `$web `
-Blob $blobName `
-Context $storageContext `
-Force | Out-Null
# Re-read Storage account and obtain static web URL
$storageAccount = Get-AzStorageAccount -Name $StorageAccountName `
-ResourceGroupName $ResourceGroupName
$url = $storageAccount.PrimaryEndpoints.Web + $blobName
# Check to make sure the url is good
$response = $null
do {
try { $response = Invoke-WebRequest -Uri $url -UseBasicParsing } catch {}
Start-Sleep -Seconds 3
} until ($response -and ($response.StatusCode -eq 200))
return $url
}
function Select-Subscription {
$subscriptions = Get-AzSubscription | Where-Object { $_.State -eq "Enabled" }
# If there are more than one subscriptions, select which one to deploy to
if ($subscriptions.count -gt 1) {
$numberedSubscriptions = @()
For ($i = 0; $i -lt $subscriptions.count; $i++) {
$numberedSubscriptions += $subscriptions[$i] | Select-Object @{Name = 'No'; Expression = { $i + 1 } }, Name, Id, TenantId
}
[int]$subNumber = $null
do {
Write-Host "Select from following subscriptions to create Resource Group and Storage Account"
Write-Host ($numberedSubscriptions | Format-Table | Out-String)
$subNumber = Read-Host "Select No"
} until ($subNumber -and ($subNumber -match "^\d+$") -and ($subNumber -le ($numberedSubscriptions.count)) -and ($subNumber -ge 1))
Set-AzContext $numberedSubscriptions[$subNumber - 1].Name | Out-Null
}
else {
Write-Error "Cannot find any subscription"
exit
}
}
function Get-AzCachedAccessToken() {
$ErrorActionPreference = 'Stop'
if (-not (Get-Module Az.Accounts)) {
Import-Module Az.Accounts
}
$azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
if (-not $azProfile.Accounts.Count) {
Write-Error "Ensure you have logged in before calling this function."
}
$currentAzureContext = Get-AzContext
$profileClient = New-Object Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient($azProfile)
Write-Debug ("Getting access token for tenant" + $currentAzureContext.Tenant.TenantId)
$token = $profileClient.AcquireAccessToken($currentAzureContext.Tenant.TenantId)
$token.AccessToken
}
function Get-AzBearerToken() {
$ErrorActionPreference = 'Stop'
('Bearer {0}' -f (Get-AzCachedAccessToken))
}
function Select-ManagementGroup {
# Get authentication token from cached credential
$bearerToken = Get-AzBearerToken
$authHeader = @{ }
$authHeader.Add('authorization', $bearerToken)
$managementGroups = @()
# Get top manamgenet groups names
$uri = "https://management.azure.com/providers/Microsoft.Management/managementGroups?api-version=2020-02-01"
$topMGsResponse = @()
$topMGsResponse = Invoke-RestMethod -Method Get -Uri $uri -Headers $authHeader
if ($topMGsResponse) {
$topMGs = @()
foreach ($topMG in $topMGsResponse.value) {
$topMGs += $topMG | Select-Object name, @{Name = 'displayName'; Expression = { $_.properties | Select-Object -ExpandProperty displayName } }, id
}
$managementGroups += $topMGs
}
else {
Write-Error "Unable to find any top level management groups"
exit
}
# Get descendants management groups
foreach ($topMG in $topMGs) {
$topMGId = $topMG.name
$uri = "https://management.azure.com/providers/Microsoft.Management/managementGroups/$topMGId/descendants?api-version=2020-02-01"
$descendantMGsResponse = $null
$descendantMGsResponse = Invoke-RestMethod -Method Get -Uri $uri -Headers $authHeader
if ($descendantMGsResponse) {
foreach ($descendantMG in $descendantMGsResponse.value) {
if ($descendantMG.type -eq 'Microsoft.Management/managementGroups') {
$managementGroups += $descendantMG | Select-Object name, @{Name = 'displayName'; Expression = { $_.properties | Select-Object -ExpandProperty displayName } }, id
}
}
}
}
# Add number to each management group
$numberedMGs = @()
For ($i = 0; $i -lt $managementGroups.count; $i++) {
$numberedMGs += $managementGroups[$i] | Select-Object @{Name = 'No'; Expression = { $i + 1 } }, Name, displayName, id
}
# Select which management group you want to deploy the policy into:
[int]$subNumber = $null
do {
Write-Host "Select from following management groups"
Write-Host ($numberedMGs | Format-Table | Out-String)
$subNumber = Read-Host "Select No"
} until ($subNumber -and ($subNumber -match "^\d+$") -and ($subNumber -le ($numberedMGs.count)) -and ($subNumber -ge 1))
$numberedMGs[$subNumber - 1].name
}